﻿using System;
using System.Linq;
using System.Text.RegularExpressions;
using NUnit.Framework;
using OpenWaves.ActivityFeed.RavenDB;
using OpenWaves.ActivityFeed.UnitTests;
using Raven.Client.Embedded;

namespace OpenWaves.ActivityFeed.UnitTests_RavenDB
{
    [TestFixture]
    class RavenDbActivityFeedServiceTests : ActivityFeedServiceTests
    {
        protected EmbeddableDocumentStore documentStore;

        [SetUp]
        public void InitializeDocumentStore()
        {
            this.documentStore = new EmbeddableDocumentStore() { RunInMemory = true };

            DocumentStoreFactory.InitializeDocumentStore(this.documentStore);
        }

        [TearDown]
        public void DisposeDocumentStore()
        {
            this.documentStore.Dispose();
        }

        protected override IActivityFeedTestSession CreateSession()
        {
            return new RavenDbActivityFeedServiceTestSession(this.documentStore.OpenSession());
        }

        [Test]
        public void Given_index_definition_created_by_UpdateFullTextSearchIndex_index_Should_be_equal_to_index_constant()
        {
            var index = documentStore.DocumentDatabase.IndexDefinitionStorage.GetIndexDefinition(typeof(UpdateFullTextSearchIndex).Name);
            string indexMap = Regex.Replace(index.Map, "[\n\r\t ]", "");
            string indexMapProperty = Regex.Replace(index.Map, "[\n\r\t ]", "");
            Assert.That(indexMap, Is.EqualTo(indexMapProperty));
        }

        [Test]
        public void Given_test_updates_Then_GetUpdates_withUserInRoles_and_searchTerm_returns_limited_numer_of_updates()
        {
            Given(service =>
            {


                using (var fakeTime = FakeTimeScope.Begin())
                {
                    fakeTime.Now = new DateTime(2000, 1, 1);
                    service.PublishUpdate(new Post("Test message"), "user1", "source",
                        new Topic[] { new Topic("publisher1"), Topic.FromUserId("user1") },
                        false, new UserGroup[] { UserGroup.FromRole("r1") });
                    fakeTime.Now = new DateTime(2000, 1, 2);
                    service.PublishUpdate(new Post("Test message 2"), "user1", "source",
                        new Topic[] { new Topic("publisher1") }, false, new UserGroup[] { UserGroup.FromRole("r2") });
                }
            });

            // pure GetUpdates
            Then(service =>
            {

                var updates = service.SearchUpdates("message").SecurityTrim(new UserGroup[] { UserGroup.FromRole("r2") }).ToList();
                Assert.That(updates.Count, Is.EqualTo(1));
                Assert.That(((Post)updates[0].Content).Text, Is.EqualTo("Test message 2"));
            });
        }

        // ***** ***** ***** ***** ***** 
        // *****  
        // *****  S E A R C H
        // *****  
        // ***** ***** ***** ***** ***** 
        [Test]
        public void Given_test_updates_Then_SearchUpdates_with_searchTerm_returns_limited_numer_of_updates()
        {
            Given(service =>
            {


                using (var fakeTime = FakeTimeScope.Begin())
                {
                    fakeTime.Now = new DateTime(2000, 1, 1);
                    var update = service.PublishUpdate(new Post("Test message"), "user1", "source",
                        new[] { new Topic("publisher1"), Topic.FromUserId("user1") }, true, Enumerable.Empty<UserGroup>());
                    update.AddComment("ccccccc", "user1");

                    fakeTime.Now = new DateTime(2000, 1, 2);
                    service.PublishUpdate(new Post("test2"), "user1", "source", new[] { new Topic("publisher1") }, true, Enumerable.Empty<UserGroup>());
                }
            });

            // pure GetUpdates
            Then(service =>
            {
                var updates = service.SearchUpdates("message").ToList();
                Assert.That(updates.Count, Is.EqualTo(1));
                Assert.That(((Post)updates[0].Content).Text, Is.EqualTo("Test message"));

                updates = service.SearchUpdates("ccccccc").ToList();
                Assert.That(updates.Count, Is.EqualTo(1));
                Assert.That(((Post)updates[0].Content).Text, Is.EqualTo("Test message"));
            });

            // pure GetUpdates forSubscriber
            Then(service =>
            {

                var updates = service.SearchUpdates("message").ForSubscriber(new Subscriber("user1")).ToList();
                Assert.That(updates.Count, Is.EqualTo(1));
                Assert.That(((Post)updates[0].Content).Text, Is.EqualTo("Test message"));

                updates = service.SearchUpdates("ccccccc").ForSubscriber(new Subscriber("user1")).ToList();
                Assert.That(updates.Count, Is.EqualTo(1));
                Assert.That(((Post)updates[0].Content).Text, Is.EqualTo("Test message"));
            });

            // pure GetUpdates forTopic
            Then(service =>
            {

                var updates = service.SearchUpdates("message").FilterByTopics(new Topic("publisher1")).ToList();
                Assert.That(updates.Count, Is.EqualTo(1));
                Assert.That(((Post)updates[0].Content).Text, Is.EqualTo("Test message"));

                updates = service.SearchUpdates("ccccccc").FilterByTopics(new Topic("publisher1")).ToList();
                Assert.That(updates.Count, Is.EqualTo(1));
                Assert.That(((Post)updates[0].Content).Text, Is.EqualTo("Test message"));
            });
        }
    }
}